// * 数组解构
let arr = ['John', 'Smith']

// 解构赋值：设置 firstName = arr[0] 和 lastName = arr[1]。
// 等价于：let firstName = arr[0], lastName = arr[1] 这种写法。
let [firstName, lastName] = arr

console.log(firstName, lastName) // John Smith

// * 与 split 结合使用
let [name1, name2] = 'John Smith'.split(' ')
console.log(name1, name2) // John Smith

// * 使用 , 号忽略元素
let [a, , c] = [1, 2, 3] // 第二个元素被跳过了
console.log(a, c) // 1 3

// * 解构赋值，= 号右侧可以是任何可迭代对象。
let [s1, , s3] = 'WYN'
console.log(s1, s3) // W N

// * 赋值给等号左侧的任何内容
let user = {}
;[user.name, user.age] = ['John', 30]
console.log(user) // {name: "John", age: 30}

// * 交换变量值的技巧
let x = 10
let y = 20
;[x, y] = [y, x]
console.log(x, y) // 20 10

// * 解构赋值，其余的'...'
let [n1, n2, ...rest] = [1, 2, 3, 4, 5]
console.log(n1, n2, rest) // 1 2 [3, 4, 5]

// * 解构赋值，默认值
let [v1, v2] = [] // 右侧没有值可以解构，也不会报错。
console.log(v1, v2) // undefined undefined

// 给“未赋值的变量”提供默认值
let [v3 = 10, v4 = 20] = [1]
console.log(v3, v4) // 1 20

// **************************************************************************************

// * 对象解构
let options = {
	title: 'Menu',
	widths: 100,
	heights: 200,
}
let { title, widths, heights } = options
console.log(title, widths, heights) // Menu 100 200

// * 顺序不重要，使用 : 设置别名，使用 = 设置默认值
let obj = {
	name: 'John',
	// age: 30,
	// city: 'New York',
	like: 'Menu',
}
let { like, name: n, city: c1 = 'Beijing', age = 20 } = obj
console.log(like, n, c1, age) // Menu John Beijing 20

// * 剩余模式（pattern）"…"
let obj2 = {
	name: 'John',
	age: 30,
	city: 'New York',
}
let { name: mz, ...objs } = obj2
console.log(mz, objs) // John { age: 30, city: 'New York' }

// * 不使用 let 时的陷阱
const obj3 = { a: 1, b: 2, c: 3 }
// { a, b, c } = obj3 这样会报错，因为会把 { } 当成代码块。
;({ a, b, c } = obj3) // 外面包裹一层括号，就可以正常解构赋值了。
console.log(a, b, c) // 1 2 3

// * 嵌套解构赋值
let optionsObj = {
	size: {
		width: 100,
		height: 200,
	},
	items: ['Cake', 'Donut'],
	extra: true,
}

let {
	size: { width, height },
	items: [item1, item2],
	titles = 'Menu',
} = optionsObj

console.log(width, height, item1, item2, titles) // 100 200 Cake Donut Menu

// * 智能函数参数(以对象形式传入，提高可读性，和解决没参数传递时也要传undefined过来的问题)
let u = {
	name: 'John',
	age: 30,
	items: ['Cake', 'Donut'],
}

// = {} 指定一个空对象作为默认值，避免没传参数时报错。
function showU({ name, age, height = 170, weight = 60, items: [v1, v2] = [] } = {}) {
	console.log(name, age, height, weight, v1, v2)
}

showU(u) // John 30 170 60 Cake Donut
showU() // undefined undefined 170 60 undefined undefined

// * 解构对象完整语法：
// let { 属性 : 变量名（别名） = 默认值, ...其余属性 } = object

// * 解构数组完整语法：
// let [item1 = defaultValue, item2, ...rest] = array

// 多维数组解构
let [[i1, i2], i3, i4] = [[1, 2], 3, 4]
console.log(i1, i2, i3, i4) // 1 2 3 4
